/**
 * 
 */
package ee.android.kinokavad.data.controllers;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import ee.android.kinokavad.data.Cinema;
import ee.android.kinokavad.data.Movie;
import ee.android.kinokavad.data.Session;
import ee.android.kinokavad.data.db.SQLiteHelper;


/**
 * @author Marko Tiidla
 *
 */
public class DataController {
	
	
	// Database fields
	private SQLiteDatabase database;
	private SQLiteHelper dbHelper;
	private String[] all_C_columns = { SQLiteHelper.COLUMN_C_ID,  SQLiteHelper.COLUMN_C_NETID, SQLiteHelper.COLUMN_C_NAME,
			SQLiteHelper.COLUMN_C_CITY, SQLiteHelper.COLUMN_C_SELECTED};
	private String[] all_M_columns = { SQLiteHelper.COLUMN_M_ID,SQLiteHelper.COLUMN_M_NETID, SQLiteHelper.COLUMN_M_TITLE,
			SQLiteHelper.COLUMN_M_DESCRIPTION, SQLiteHelper.COLUMN_M_GENRE,
			SQLiteHelper.COLUMN_M_YOUTUBE, SQLiteHelper.COLUMN_M_IMDB,
			SQLiteHelper.COLUMN_M_PICTURE};
	private String[] all_S_columns = { SQLiteHelper.COLUMN_S_ID, SQLiteHelper.COLUMN_S_CINEMAID,
			SQLiteHelper.COLUMN_S_MOVIEID, SQLiteHelper.COLUMN_S_DATE,
			SQLiteHelper.COLUMN_S_TIME, SQLiteHelper.COLUMN_S_PICTURE};


	private List<Movie> movies;

	private ArrayList<Session> sessions;

	private List<Cinema> cinemas;

	private static final String SOAP_CINEMAS = "http://www.microsoft.com/testwebservices123/getCinemasList";
    private static final String METHOD_CINEMAS = "getCinemasList";
    private static final String SOAP_SESSIONS = "http://www.microsoft.com/testwebservices123/getAllSessionsForDay";
    private static final String METHOD_SESSIONS = "getAllSessionsForDay";
    private static final String SOAP_MOVIES = "http://www.microsoft.com/testwebservices123/getAllMovieswithIds";
    private static final String METHOD_MOVIES = "getAllMovieswithIds";
    private static final String NAMESPACE = "http://www.microsoft.com/testwebservices123/";
    private static final String URL = "http://sandstorm.cs.ut.ee/MA/silver91/WebService1.asmx?WSDL";
    
    public DataController(Context context) {
    	dbHelper = new SQLiteHelper(context);
    }
    
    public void open() throws SQLException {
		database = dbHelper.getWritableDatabase();
	}

	public void close() {
		dbHelper.close();
	}
    
	public void addCinemaToDatabase(Cinema cinema) {
		ContentValues values = new ContentValues();
		values.put(SQLiteHelper.COLUMN_C_NETID, cinema.getNetId());
		values.put(SQLiteHelper.COLUMN_C_NAME, cinema.getName());
		values.put(SQLiteHelper.COLUMN_C_CITY, cinema.getCity());
		int val =  cinema.isSelected() ? 1:0;
		values.put(SQLiteHelper.COLUMN_C_SELECTED, val);
		Log.d(cinema.getName(), cinema.isSelected()+"");
		
		database.insert(SQLiteHelper.TABLE_CINEMAS, null, values);
	}

	public void deleteCinema(Cinema cinema) {
		long id = cinema.getId();
		System.out.println("Cinema deleted with id: " + id);
		database.delete(SQLiteHelper.TABLE_CINEMAS, SQLiteHelper.COLUMN_C_ID
				+ " = " + id, null);
	}
	
	public void alterCinemas(){
		database.execSQL("delete from " + SQLiteHelper.TABLE_CINEMAS+";");
		for(Cinema cinema: cinemas){
			addCinemaToDatabase(cinema);
		}
	}

	public boolean loadAllCinemasFromDatabase() {
		cinemas = new ArrayList<Cinema>();
		boolean available = false;
		Cursor cursor = database.query(SQLiteHelper.TABLE_CINEMAS,
				all_C_columns, null, null, null, null, null);

		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			Cinema cinema = cursorToCinema(cursor);
			cinemas.add(cinema);
			available = true;
			cursor.moveToNext();
			Log.d(cinema.getName(), cinema.isSelected()+"");
		}
		// Make sure to close the cursor
		cursor.close();
		return available;
	}

	private Cinema cursorToCinema(Cursor cursor) {
		Cinema cinema = new Cinema( (int) cursor.getLong(0), (int) cursor.getLong(1), cursor.getString(2), cursor.getString(3));
		cinema.setSelected(cursor.getLong(4) == 1);
		return cinema;
	}
	
	
	public void addMovieToDatabase(Movie movie) {
		ContentValues values = new ContentValues();
		values.put(SQLiteHelper.COLUMN_M_NETID, movie.getNetId());
		values.put(SQLiteHelper.COLUMN_M_TITLE, movie.getTitle());
		values.put(SQLiteHelper.COLUMN_M_DESCRIPTION, movie.getDescription());
		values.put(SQLiteHelper.COLUMN_M_GENRE, movie.getGenre());
		values.put(SQLiteHelper.COLUMN_M_YOUTUBE,movie.getYoutubeLink());
		values.put(SQLiteHelper.COLUMN_M_IMDB, movie.getImdbLink());
		values.put(SQLiteHelper.COLUMN_M_PICTURE, movie.getPictureLink());
		
		database.insert(SQLiteHelper.TABLE_MOVIES, null, values);
	}

	public void deleteMovie(Movie movie) {
		long id = movie.getId();
		System.out.println("Movie deleted with id: " + id);
		database.delete(SQLiteHelper.TABLE_MOVIES, SQLiteHelper.COLUMN_M_ID
				+ " = " + id, null);
	}

	public boolean loadAllMoviesFromDatabase() {
		movies = new ArrayList<Movie>();
		boolean available = false;
		Cursor cursor = database.query(SQLiteHelper.TABLE_MOVIES,
				all_M_columns, null, null, null, null, null);

		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			Movie movie = cursorToMovie(cursor);
			movies.add(movie);
			available = true;
			cursor.moveToNext();
		}
		// Make sure to close the cursor
		cursor.close();
		return available;
	}

	private Movie cursorToMovie(Cursor cursor) {
		Movie movie = new Movie((int)cursor.getLong(0),(int)cursor.getLong(1),
				cursor.getString(2), cursor.getString(3),
				cursor.getString(4), cursor.getString(5), cursor.getString(6), cursor.getString(7));
		return movie;
	}
	
	
	
	public void addSessionToDatabase(Session session) {
		ContentValues values = new ContentValues();
		values.put(SQLiteHelper.COLUMN_S_CINEMAID, session.getCinemaId());
		values.put(SQLiteHelper.COLUMN_S_MOVIEID, session.getMovieId());
		values.put(SQLiteHelper.COLUMN_S_DATE, session.getDate());
		values.put(SQLiteHelper.COLUMN_S_TIME,session.getTime());
		values.put(SQLiteHelper.COLUMN_S_PICTURE, session.getPictureLink());
		
		database.insert(SQLiteHelper.TABLE_SESSIONS, null, values);
	}

	public void deleteSession(Session session) {
		long id = session.getId();
		System.out.println("Session deleted with id: " + id);
		database.delete(SQLiteHelper.TABLE_SESSIONS, SQLiteHelper.COLUMN_S_ID
				+ " = " + id, null);
	}

	public boolean loadAllSessionsFromDatabase() {
		sessions = new ArrayList<Session>();
		boolean available = false;
		Cursor cursor = database.query(SQLiteHelper.TABLE_SESSIONS,
				all_S_columns, null, null, null, null, null);

		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			Session session = cursorToSession(cursor);
			sessions.add(session);
			available = true;
			cursor.moveToNext();
		}
		// Make sure to close the cursor
		for (Movie movie: movies){
			for (Session session : sessions){
				if (session.getMovieId() == movie.getNetId()){
					session.setMovie(movie);
				}
			}
		}
		cursor.close();
		return available;
	}

	private Session cursorToSession(Cursor cursor) {
		Session session = new Session((int)cursor.getLong(0),(int) cursor.getLong(1),(int) cursor.getLong(2),
				cursor.getString(3), cursor.getString(4), cursor.getString(5));
		return session;
	}
    
    
    
    
    
    
    
    /**
     * Download all available cinemas from webservice.
     * @return List
     */
	public void downloadAllCinemas(){
		
		cinemas = new ArrayList<Cinema>();
		
		try{
			
			SoapObject request = new SoapObject(NAMESPACE, METHOD_CINEMAS);
			
			SoapSerializationEnvelope envelope= new SoapSerializationEnvelope(SoapEnvelope.VER11);
		
			envelope.dotNet = true;
			envelope.setOutputSoapObject(request);
			
			HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
			
			androidHttpTransport.call(SOAP_CINEMAS, envelope);
			
			SoapObject result = (SoapObject)envelope.getResponse();
			
			for (int i = 0; i < result.getPropertyCount(); i++){
				SoapObject object = (SoapObject) result.getProperty(i);
				String name = object.getProperty("Name").toString();
				String city = object.getProperty("City").toString();
				int id = Integer.parseInt(object.getProperty("id").toString());
				Cinema cinema = new Cinema(id, id, name, city);
				if (i==0) {
					cinema.setSelected(true);
				}
				cinemas.add(cinema);
				addCinemaToDatabase(cinema);
				
			}
			
		} catch (Exception e){}
		
	}
	
	/**
	 * Download all sessions from web service for given date + 4 next days.
	 * @param year
	 * @param month
	 * @param day
	 * @return List
	 */
	public void downloadAllSessions(int year, int month, int day){
		sessions = new ArrayList<Session>();
		
		try {
			SoapObject request = new SoapObject(NAMESPACE, METHOD_SESSIONS);
			
			SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
			
			request.addProperty("year", year);
			request.addProperty("month", month);
			request.addProperty("day", day);
			
			envelope.dotNet = true;
			envelope.setOutputSoapObject(request);
			
			HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
			
			androidHttpTransport.call(SOAP_SESSIONS, envelope);
			
			SoapObject result = (SoapObject)envelope.getResponse();
			
			database.execSQL("delete from " + SQLiteHelper.TABLE_SESSIONS + ";");
			for (int i = 0; i < result.getPropertyCount(); i++){
				SoapObject object = (SoapObject) result.getProperty(i);
				String date = object.getProperty("date").toString();
				String time = object.getProperty("time").toString();
				String pictureLink = object.getProperty("pictureLink").toString();
				int id = Integer.parseInt(object.getProperty("id").toString());
				int cinemaId = Integer.parseInt(object.getProperty("cinemaId").toString());
				int movieId = Integer.parseInt(object.getProperty("movieId").toString());
				Session session = new Session(id, cinemaId, movieId, date, time, pictureLink);
				sessions.add(session);
				addSessionToDatabase(session);
			}
			
		} catch (Exception e){}
		
		if (sessions.size() != 0){
			String ids = generateMovieIdList();
			downloadAllMovies(ids);
			
		}
		
	}
	/**
	 * Sorts sessions and returns only sessions for day for selected cinema.
	 * Notice that this method deals with Java dates, no need to add extra +1 for month here!
	 * @param year
	 * @param month
	 * @param day
	 * @return ArrayList<Session> Sessions for given day and cinema
	 */
	public ArrayList<Session> getAllSessionsForDayForChosenCinema(int year, int month, int day){

		ArrayList<Session> daysessions = new ArrayList<Session>();

		SimpleDateFormat df = new SimpleDateFormat("d.M.y");
		Date d = new Date();
		Calendar newCalendar = Calendar.getInstance();
		for (Cinema cinema : cinemas) {
			if (cinema.isSelected()){
				for (Session session : sessions){
					if(session.getCinemaId() == cinema.getNetId()){
						try {
							d = df.parse(session.getDate());
						} catch (ParseException e) {
							e.printStackTrace();
						}
						newCalendar.setTime(d);
						if (day == newCalendar.get(Calendar.DAY_OF_MONTH) &&
								month == newCalendar.get(Calendar.MONTH) &&
								year == newCalendar.get(Calendar.YEAR))
						{
							daysessions.add(session);
						}
					}
				}
			}
		}
		

		return daysessions;
	}
	/**
	 * Download all movies from webservice with given ids. Is called from inside getAllSessionsForDay().
	 * @param ids
	 * @return List
	 */
	public List<Movie> downloadAllMovies(String ids){
		
		movies = new ArrayList<Movie>();
		
		try {
			SoapObject request = new SoapObject(NAMESPACE, METHOD_MOVIES);
			
			SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapSerializationEnvelope.VER11);
			
			request.addProperty("idsstring", ids);
			
			envelope.dotNet = true;
			envelope.setOutputSoapObject(request);
			
			HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
			
			androidHttpTransport.call(SOAP_MOVIES, envelope);
			
			SoapObject result = (SoapObject)envelope.getResponse();
			
			database.execSQL("delete from " + SQLiteHelper.TABLE_MOVIES + ";");
			for (int i = 0; i < result.getPropertyCount(); i++){
				SoapObject object = (SoapObject) result.getProperty(i);
				int id = Integer.parseInt(object.getProperty("id").toString());
				String Title = object.getProperty("Title").toString();
				String Description = object.getProperty("Description").toString();
				String Genre = object.getProperty("Genre").toString();
				String youtubeLink = object.getProperty("youtubeLink").toString();
				String imdbLink = object.getProperty("imdbLink").toString();
				if (Title.contains("anyType{}")){
					Title = "";
				}
				if (Description.contains("anyType{}")){
					Description = "";
				}
				if (Genre.contains("anyType{}")){
					Genre = "";
				}
				if (youtubeLink.contains("anyType{}")){
					youtubeLink = "";
				}
				if (imdbLink.contains("anyType{}")) {
					imdbLink = "";
				}
						
				Movie movie = new Movie(id, id, Title, Description, Genre, youtubeLink, imdbLink, "");
				for (int j = 0; j < sessions.size(); j++) {
					if (sessions.get(j).getMovieId() == id){
						sessions.get(j).setMovie(movie);
						String picturelink = sessions.get(j).getPictureLink();
						if (! picturelink.contains("http://")){
							picturelink = "http://www.kavad.ee/picture/" + picturelink;
						}
						movie.setPictureLink(picturelink);
					} 
				}
				movies.add(movie);
				addMovieToDatabase(movie);
				
			}
			
		} catch (Exception e){}
		
		return movies;
		
	}
	
	public String generateMovieIdList(){
		
		Log.d("Sessions size", sessions.size()+"");
		List<Integer> checkList = new ArrayList<Integer>();
        StringBuilder result = new StringBuilder();
        result.append(sessions.get(0).getMovieId());
        checkList.add(sessions.get(0).getMovieId());
        
        for (int i = 1; i < sessions.size(); i++)
        {
            if(! checkList.contains(sessions.get(i).getMovieId()))
            {
                checkList.add(sessions.get(i).getMovieId());
                result.append(" "+sessions.get(i).getMovieId());
            }
        }

        return result.toString();
		
	}
	
	
	/**
	 * @return List of all movies.
	 */
	public List<Movie> getMovies() {
		return movies;
	}
	
	/**
	 * @return List of all sessions.
	 */
	public List<Session> getSessions() {
		return sessions;
	}
	
	/**
	 * @return List of all cinemas.
	 */
	public List<Cinema> getCinemas() {
		return cinemas;
	}
	
	
}
